﻿using System.Diagnostics;
using System.Net;
using System.Net.Sockets;

namespace Gobang.ToolClass.Networking.UDP
{
    public class UDPClientTool : IClientNetworking
    {
        private UdpClient _udpClient;
        private Action<byte[], IPEndPoint> _dataArrival;
        private readonly IPAddress _iPAddress;
        private readonly int _port;
        private readonly IPEndPoint _localHost;
        private IPEndPoint _remoteEP;
        private volatile bool active = false;
        private Thread _thread;
        public UDPClientTool(string iPAddress, int port)
        {
            if (!IPAddress.TryParse(iPAddress, out IPAddress address))
                throw new Exception("IP地址不正确");

            _iPAddress = address;
            _port = port;

            _localHost = new IPEndPoint(address, port);
        }
        public UDPClientTool(IPAddress address, int port)
        {
            if (address == null)
                throw new Exception("IP地址不正确");

            _port = port;
            _iPAddress = address;

            _localHost = new IPEndPoint(address, port);
        }
        #region 属性
        public bool Active
        {
            get { return active; }
            set
            {
                if (active == value)
                    return;

                active = value;
                if (active)
                    OpenSocket();
                else
                    CloseSocket();
            }
        }
        public Action<byte[], IPEndPoint> DataArrival
        {
            get => _dataArrival;
            set
            {
                _dataArrival = value;
            }
        }
        IPEndPoint IClientNetworking.LocalHostEP { get => _localHost; }
        IPEndPoint IClientNetworking.RemoteEP { get => _remoteEP; }

        #endregion

        #region 方法
        private void OpenSocket()
        {
            if (_udpClient != null)
            {
                _udpClient.Close();
                _udpClient.Dispose();
            }
            _udpClient = new UdpClient(_localHost);

            Listener();
        }
        private void Listener()
        {
            _thread = new Thread(GetUDPData);
            _thread.Start();
        }
        private volatile bool _close = false;
        private void GetUDPData()
        {
            while (active)
            {
                try
                {
                    if (DataArrival != null)
                    {
                        byte[] buffer = _udpClient.Receive(ref _remoteEP);
                        DataArrival(buffer, _remoteEP);
                    }
                    Thread.Sleep(0);
                }
                catch (Exception ex)
                {
#if DEBUG
                    Trace.WriteLine("UDPClientTool.GetUDPData：" + ex.Message);
                    Thread.Sleep(0);
#endif
                }
            }
        }
        private void CloseSocket()
        {
            if (_udpClient != null)
            {
                _udpClient.Close();
                _udpClient.Dispose();
            }
            if (_thread != null)
            {
                Thread.Sleep(30);
                try
                {
                    //_thread.Interrupt();// 中断
                }
                catch (Exception ex)
                {
#if DEBUG 
                    Trace.WriteLine("UDPClientTool.CloseSocket：" + ex.Message);
#endif
                }
            }
        }
        public bool Send(string ip, int port, byte[] data)
        {
            bool status = false;
            if (!IPAddress.TryParse(ip, out IPAddress address))
                throw new Exception("IP地址不正确");
            try
            {
                if (_udpClient == null)
                {
#if DEBUG
                    Trace.WriteLine("UDP未开启");
#endif
                    return status;
                }

                IPEndPoint iPEndPoint = new IPEndPoint(address, port);
                status = _udpClient.Send(data, data.Length, iPEndPoint) > 0;
            }
            catch (Exception ex)
            {
#if DEBUG
                Trace.WriteLine("UDPClientTool.Send：" + ex.Message);
#endif
            }
            return status;
        }
        public bool Send(IPEndPoint iPEndPoint, byte[] data)
        {
            bool status = false;
            if (iPEndPoint == null)
                throw new Exception("IP地址不正确");
            try
            {
                if (_udpClient == null)
                {
#if DEBUG
                    Trace.WriteLine("UDP未开启");
#endif
                    return status;
                }

                status = _udpClient.Send(data, data.Length, iPEndPoint) > 0;
            }
            catch (Exception ex)
            {
#if DEBUG
                Trace.WriteLine("UDPClientTool.Send-179：" + ex.Message);
#endif
            }
            return status;
        }
        public void Close()
        {
            try
            {
                //if (_thread != null)
                //{
                //    _thread.Interrupt();
                //    _thread.Join();
                //}

                this.Active = false;
            }
            catch (Exception ex)
            {
#if DEBUG
                Trace.WriteLine("UDPClientTool.Close：" + ex.Message);
#endif
            }
        }
        #endregion
    }
}
